﻿package kliment.controls {
	import caurina.transitions.Equations;
	import caurina.transitions.Tweener;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import kliment.display.MovieClipButton;
	import kliment.events.MovieClipButtonEvent;
	import kliment.layout.SpriteCanvas;
	import kliment.utils._Sprite;
	
	/**
	 * ...
	 * @author	Kliment
	 * @version	1.3.15
	 * 
	 * class name: kliment.controls.ComboBox
	 */
	public class ComboBox extends ControlsAbstract {
		protected var _speedAnimation:Number = .4;
		private var _target_mc:MovieClipButton;
		private var _parent_mc:Sprite;
		private var _contentBox_mc:MovieClip;
		private var _target_box_cell:SpriteCanvas;
		private var _content_mc:MovieClip;
		private var _content_scroller_mc:MovieClip;
		private var _content_box_mc:MovieClip;
		private var _content_box_mask_mc:MovieClip;
		private var _content_box_cell_mc:MovieClip;
		private var _layout_buttons_mc:Sprite;
		private var _layout_focus_mc:Sprite;
		private var _scroller:Scroller;
		private var _scrollerBox:ScrollerBox;
		private var _list_box:ListBox;
		private var _itemRender:Class;
		private var _dataProvider:*;
		private var _selectItem:*;
		private var _rowCount:Number = 5;
		private var _selectedIndex:Number = -1;
		private var _hidePosition:Number;
		private var _isShow:Boolean = false;
		private var _isDownPos:Boolean = true;
		private var _v_distance:Number = 0;
		
		public function ComboBox(target_mc:MovieClipButton, contentBox:MovieClip, parent_mc:Sprite) {
			super();
			_target_mc = target_mc;
			_contentBox_mc = contentBox;
			_parent_mc = parent_mc;
			
			target_mc.addEventListener(MovieClipButtonEvent.RELEASE, _relaseHandler);
		}
		
		private function _relaseHandler(event:Event):void {
			if (_target_box_cell) {
				if (_isShow) 
					close();
				else if (_target_box_cell.parent)
					open();
				else 
					_create();
			} else {
				_create();
			}
		}
		
		private function _stageMouseHandler(event:MouseEvent):void {
			if (_isShow) {
				switch(event.type) {
					case MouseEvent.CLICK:
						if (!_inSpace()) {
							close();
						}
					break;
				}
			}
		}
		
		private function _create():void {
			if (!_parent_mc) return;
			
			if (_target_box_cell && !_target_box_cell.parent) {
				
			} else {
				_target_box_cell = new SpriteCanvas();
				_content_mc = _contentBox_mc;
				_content_scroller_mc = _content_mc['scroller_mc'];
				_content_box_mc = _content_mc['content_box_mc'];
				_content_box_mask_mc = _content_box_mc['mask_mc'];
				_content_box_cell_mc = _content_box_mc['content_mc'];
				
				if (_content_scroller_mc) 
					_scrollerBox = new ScrollerBox(_content_scroller_mc);
				else 
					_scrollerBox = null;
				
				_layout_focus_mc = new Sprite();
				_layout_buttons_mc = new Sprite();
				
				_createList();
				_setPosition();
				_content_mc.y = _hidePosition;
				
				_content_box_cell_mc.addChild(_layout_focus_mc);
				_content_box_cell_mc.addChild(_layout_buttons_mc);
				_target_box_cell.addChild(_content_mc);
			}
			
			_parent_mc.addChild(_target_box_cell);
			_scroller.enable = true;
			_parent_mc.stage.addEventListener(MouseEvent.CLICK, _stageMouseHandler);
			_target_box_cell.addEventListener(Event.ENTER_FRAME, _enterFrameHandler);
			open();
		}
		
		private function _createList():void {
			if (_list_box)
				_list_box.erase();
			_list_box = new ListBox(_layout_buttons_mc, Orientation.VERTICAL);
			_list_box.vInterval = 1;
			_list_box.itemRender = _itemRender;
			_list_box.dataProvider = _dataProvider;
			_setListeners(_list_box);
			var w:Number = Math.max(_target_mc.width, _layout_buttons_mc.width);
			var h:Number = _layout_buttons_mc.height
			_target_box_cell.width = w;
			_list_box.width = w;
			_content_box_mask_mc.height = h;
			_target_box_cell.height = h;
			_updateRowCount();
			
			if (_selectedIndex > -1) {
				var item:* = _list_box.getItem(_selectedIndex);
				item.setFocus();
				selectedIndex = _selectedIndex;
				
				_scroller.showPart(item.y, item.y + item.height);
			}
		}
		
		private function _setListeners(listBox:ListBox):void {
			var length:int = listBox.length;
			for (var i:int = 0; i < length; ++i ) {
				var item:MovieClipButton = listBox.getItem(i);
				item.addEventListener(MovieClipButtonEvent.MOUSE_DOWN, _itemMouseHandler);
				item.addEventListener(MovieClipButtonEvent.ROLL_OVER, _itemMouseHandler);
				item.addEventListener(MovieClipButtonEvent.ROLL_OUT, _itemMouseHandler);
				item.addEventListener(MovieClipButtonEvent.RELEASE_OUTSIDE, _itemMouseHandler);
			}
		}
		
		private function _enterFrameHandler(event:Event):void {
			_setPosition();
		}
		
		private function _itemMouseHandler(event:MovieClipButtonEvent):void {
			var eventBtn:* = event.target;
			switch(event.type) {
				case MovieClipButtonEvent.ROLL_OVER:
					if (_selectItem != eventBtn)
						eventBtn.setFocus();
				break;
				
				case MovieClipButtonEvent.ROLL_OUT:
				case MovieClipButtonEvent.RELEASE_OUTSIDE:
					if (_selectItem != eventBtn)
						eventBtn.resetFocus();
				break;
				
				case MovieClipButtonEvent.MOUSE_DOWN:
					if (_selectItem != eventBtn) {
						if (_selectItem)
							_selectItem.resetFocus();
						_selectItem = eventBtn;
						_selectedIndex = eventBtn.index;
						dispatchEvent(new Event(Event.CHANGE));
						close();
					}
				break;
			}
		}
		
		private function _updateRowCount():void {
			var cellHeight:Number = _layout_buttons_mc.height;
			var lashShow:DisplayObject = _list_box.getItem(_rowCount - 1);
			if (lashShow) 
				cellHeight = lashShow.y + lashShow.height;
			_target_box_cell.height = cellHeight;
			_content_box_mask_mc.height = cellHeight;
			
			if (_scrollerBox) {
				_scrollerBox.space_btn.height = _content_box_mask_mc.height;
			}
			if (_scroller)
				_scroller.remove();
			_scroller = new Scroller(_content_box_cell_mc, _content_box_mask_mc, 
									{
										scrollerBox:_scrollerBox, 
										orientation:Orientation.VERTICAL, 
										scaleSeeker:true, 
										keyboardEnable:false,
										mouseGestureEnable:false
									});
	}
		
		private function _setPosition():void {
			var pos:Point = _parent_mc.globalToLocal(_target_mc.localToGlobal(new Point()));
			
			var tpos:Point = new Point();
			_parent_mc.globalToLocal(tpos);
			var th:Number = pos.y - tpos.y;
			
			var bpox:Point = new Point(0, _target_mc.stage.stageHeight);
			_parent_mc.globalToLocal(bpox);
			var bh:Number = bpox.y - pos.y - _target_mc.height;
			
			_target_box_cell.x = pos.x;
			
			if (bh >= _target_box_cell.height) {
				_target_box_cell.y = pos.y + _target_mc.height + _v_distance;
				_hidePosition = -_layout_buttons_mc.height;
				_isDownPos = true;
			} else {
				_target_box_cell.y = pos.y - _target_box_cell.height - _v_distance;
				_hidePosition = _target_box_cell.height;
				_isDownPos = false;
			}
		}
		
		private function _inSpace():Boolean {
			if (!_Sprite.hitTestBoundsMouse(_target_box_cell) && !_Sprite.hitTestBoundsMouse(_target_mc))
				return false;
			return true;
		}
		
		public function get itemRender():Class { return _itemRender }
		public function set itemRender(class_name:Class):void {
			_itemRender = class_name;
			if (_target_box_cell)
				_createList();
		}
		
		public function get dataProvider():* { return _dataProvider }
		public function set dataProvider(value:*):void {
			_dataProvider = value;
			if (_target_box_cell)
				_createList();
		}
		
		public function get selectedIndex():Number { return _selectedIndex }
		public function set selectedIndex(index:Number):void {
			var c_index:Number = _selectedIndex;
			if (_list_box) {
				var item:* = _list_box.getItem(index);
				_selectItem = item;
				_selectedIndex = (item)?index: -1;
			} else {
				_selectedIndex = index;
			}
			if (c_index != index)
				dispatchEvent(new Event(Event.CHANGE));
		}
		
		public function get value():* { return _dataProvider[selectedIndex] }
		
		public function get rowCount():Number { return _rowCount; }
		public function set rowCount(value:Number):void {
			_rowCount = Math.max(1, value);
			if (_target_box_cell)
				_updateRowCount();
		}
		
		public function get selectedItem():Object { return _dataProvider[_selectedIndex] }
		
		public function get v_distance():Number { return _v_distance; }
		public function set v_distance(value:Number):void {
			_v_distance = value;
			if (_target_box_cell)
				_setPosition()
		}
		
		public function open():void {
			_isShow = true;
			Tweener.addTween(_content_mc, { y:0, time:_speedAnimation, transition:Equations.easeOutCirc } );
			dispatchEvent(new Event(Event.OPEN));
		}
		
		public function close():void {
			if (_isShow) {
				_isShow = false;
				Tweener.addTween(_content_mc, { y:_hidePosition, time:_speedAnimation, transition:Equations.easeInCubic, onComplete:_remove } );
				dispatchEvent(new Event(Event.CLOSE));
			}
		}
		
		private function _remove():void {
			if (_scroller)
				_scroller.enable = false;
			_parent_mc.stage.removeEventListener(MouseEvent.CLICK, _stageMouseHandler);
			if (_target_box_cell) {
				_target_box_cell.removeEventListener(Event.ENTER_FRAME, _enterFrameHandler);
				_target_box_cell.remove();
			}
		}
		
		public function remove():void {
			Tweener.removeTweens(_content_mc);
			if (_scroller) 
				_scroller.remove();
			_parent_mc.stage.removeEventListener(MouseEvent.CLICK, _stageMouseHandler);
			if (_target_box_cell) {
				_target_box_cell.removeEventListener(Event.ENTER_FRAME, _enterFrameHandler);
				_target_box_cell.remove();
			}
			_target_box_cell = null;
		}
	}

}